www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char16/fontcombo/FontCombo.cpp

    // FontBox.cpp : implementation file
//

#include "Stdafx.h"
#include "resource.h"
#include "FontCombo.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Constant and should not be changed unless 
// image IDB_GLYPH is changed
#define GLYPH_WIDTH 15 

//////////////////////////////////////////////////////////////////////////
// ? Paramax Technology Limited                                         // 
// ----------------------------                                         //
//                                                                      //
// The author accepts no liablility for injury or loss of profits       // 
// if this software is used. You willingness to use this software       //
// indicates you accept total liability                                 //
//                                                                      // 
//////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// CFontCombo

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CACFontCombo::CFontCombo
//
// DESCRIPTION:	Constructor
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
CFontCombo::CFontCombo()
{
	// Load up glyphs
	m_img.Create(IDB_GLYPHS,15,1,RGB(255,0,255));

}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::~CFontCombo
//
// DESCRIPTION:	Constructor
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
CFontCombo::~CFontCombo()
{
}

BEGIN_MESSAGE_MAP(CFontCombo, CComboBox)
	//{{AFX_MSG_MAP(CFontCombo)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnKillfocus)
	ON_CONTROL_REFLECT(CBN_SETFOCUS, OnSetfocus)
	ON_CONTROL_REFLECT(CBN_CLOSEUP, OnCloseUp)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFontCombo message handlers
// Overridables for onwerdraw combos
void CFontCombo::DeleteItem(LPDELETEITEMSTRUCT) 
{
}
// Overridables for onwerdraw combos
void CFontCombo::MeasureItem(LPMEASUREITEMSTRUCT) 
{
}

// Initialize fonts for combo
int CFontCombo::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CComboBox::OnCreate(lpCreateStruct) == -1)
		return -1;

	Initialize();

	return 0;
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::DrawItem
//
// DESCRIPTION:	Owner draw to render bitmap and font name
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
{
	ASSERT(lpDIS->CtlType == ODT_COMBOBOX); // We've gotta be a combo

	// Lets make a CDC for ease of use
	CDC *pDC = CDC::FromHandle(lpDIS->hDC);
	
	ASSERT(pDC); // Attached failed
	
	CRect rc(lpDIS->rcItem);
	
	// Draw focus rectangle
	if (lpDIS->itemState & ODS_FOCUS)
		pDC->DrawFocusRect(rc);
	
	// Save off context attributes
	int nIndexDC = pDC->SaveDC();

	CBrush brushFill;
	
	// Draw selection state
	if (lpDIS->itemState & ODS_SELECTED)
	{
		brushFill.CreateSolidBrush(::GetSysColor(COLOR_HIGHLIGHT));
		pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
	}
	else
		brushFill.CreateSolidBrush(pDC->GetBkColor());

	pDC->SetBkMode(TRANSPARENT);
	pDC->FillRect(rc, &brushFill);

	CString strCurFont,strNextFont;
	GetLBText(lpDIS->itemID,strCurFont);

	CFontObj* pFontObj;
	m_mapFonts.Lookup(strCurFont,pFontObj);

	ASSERT(pFontObj != NULL);
	DWORD dwData = pFontObj->GetFlags();
	
	// Render Bitmaps
	if (dwData & TRUETYPE_FONT)
		m_img.Draw(pDC,1, CPoint(rc.left,rc.top),ILD_TRANSPARENT);

	if (dwData & PRINTER_FONT)
		m_img.Draw(pDC,0, CPoint(rc.left,rc.top),ILD_TRANSPARENT);
	
	int nX = rc.left; // Save for lines

	rc.left += GLYPH_WIDTH + 2; // Text Position
	pDC->TextOut(rc.left,rc.top,strCurFont);

	// GetItemData - return font in use
	if (GetItemData(lpDIS->itemID))
	{
		GetLBText(lpDIS->itemID+1,strNextFont);
		CFontObj* pFontObjNext;
		m_mapFonts.Lookup(strNextFont,pFontObjNext);

		if (!GetItemData(lpDIS->itemID+1))
		{
			// Draw font MRU separator ==============
			//                         
			TEXTMETRIC tm;
			pDC->GetTextMetrics(&tm);

			pDC->MoveTo(nX,rc.top+tm.tmHeight);
			pDC->LineTo(rc.right,rc.top+tm.tmHeight);

			pDC->MoveTo(nX,rc.top+tm.tmHeight+2);
			pDC->LineTo(rc.right,rc.top+tm.tmHeight+2);
	
		}
	}

	// Restore State of context
	pDC->RestoreDC(nIndexDC);
}


// As it says...EnumerateFonts on the system
BOOL CFontCombo::EnumerateFonts()
{
	HDC hDC;
	
	// Get screen fonts
	hDC = ::GetWindowDC(NULL);
	
	LOGFONT lf;
	
	ZeroMemory(&lf,sizeof(lf));
	lf.lfCharSet = ANSI_CHARSET;

	if (!EnumFontFamiliesEx(
			hDC,	// handle to device context
			&lf,	// pointer to logical font information
			(FONTENUMPROC)EnumFamScreenCallBackEx,	// pointer to callback function
			(LPARAM) this,	// application-supplied data
			(DWORD) 0))
		return FALSE;

	::ReleaseDC(NULL,hDC);	

	// Now get printer fonts
	CPrintDialog dlg(FALSE);
	if (AfxGetApp()->GetPrinterDeviceDefaults(&dlg.m_pd))
	{
		// GetPrinterDC returns a HDC so attach it
		hDC= dlg.CreatePrinterDC();
		ASSERT(hDC != NULL);

		ZeroMemory(&lf,sizeof(lf));
		lf.lfCharSet = ANSI_CHARSET;

		if (!EnumFontFamiliesEx(
				hDC,	// handle to device context
				&lf,	// pointer to logical font information
				(FONTENUMPROC)EnumFamPrinterCallBackEx,	// pointer to callback function
				(LPARAM) this,	// application-supplied data
				(DWORD) 0))
			return FALSE;

	}
	
	return TRUE; // All's ok
}


////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::OnDestroy
//
// DESCRIPTION:	Destroys font objects
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::OnDestroy() 
{
	POSITION pos = m_mapFonts.GetStartPosition();
	
	while (pos)
	{
		CString strKey;
		CFontObj* pFontObj;
		m_mapFonts.GetNextAssoc(pos,strKey,pFontObj);
		delete pFontObj;
	}

	CComboBox::OnDestroy();
}


////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::SetFontInUse
//
// DESCRIPTION:	Flags a font that is in use, similar to MS Words font MRU list
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::SetFontInUse(const CString& strFont)
{
	CFontObj *pFontObj;
	CString strFontDesc;
	
	// Find the desired font
	if (m_mapFonts.Lookup(strFont,pFontObj))
	{
		// Check the font is not already in use
		if (!pFontObj->GetFontInUse())
		{
			// Set the font as the top most and selected font
			pFontObj->SetFontInUse(TRUE);
			InsertString(0,strFont);
			SetItemData(0,DWORD(1));

			// Only hold six MRU'ed fonts
			// so drop the 7th.
			if (GetItemData(6))
			{
				GetLBText(6,strFontDesc);
				if (!strFontDesc.IsEmpty())
				{
					if (m_mapFonts.Lookup(strFontDesc,pFontObj))
					{
						pFontObj->SetFontInUse(FALSE);
						DeleteString(6);
					}
				}
			}
		}
		else
		{
			// If font is aleady MRU'ed position it as the first font
			int nSel = FindString(-1,strFont);
	
			if (nSel != CB_ERR)
			{
				// Remove from original position
				DeleteString(nSel);
				// Restore to begining of list
			
				InsertString(0,strFont);
				SetItemData(0,TRUE); // Mark as selected
				SetCurSel(0);	// Bring as current selection
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::OnKillfocus
//
// DESCRIPTION:	Set up the current font
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::OnKillfocus() 
{
	SetCurrentFont();
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::OnSetfocus
//
// DESCRIPTION:	Save current font
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::OnSetfocus() 
{
	// Save off original font
	GetWindowText(m_strFontSave);	
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::SetCurrentFont
//
// DESCRIPTION:	Set up the current font
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::SetCurrentFont()
{
	CString strSelFont;

	// Change font in edit box is a known font
	// otherwise reject and restore orginal
	int nSel = GetCurSel();

	if (nSel == CB_ERR)
	{
		GetWindowText(strSelFont);
		nSel = FindStringExact(-1,strSelFont);
		
		if (nSel == CB_ERR)
		{
			SetWindowText(m_strFontSave);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::OnCloseUp
//
// DESCRIPTION:	Hide tip window and set font name
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::OnCloseUp()
{
	int nSel;	

	CString strFont;
	// Set Face Name
	SetCurrentFont();
	nSel = GetCurSel();
	if (nSel != CB_ERR)
		GetLBText(nSel,strFont);

	SetFontInUse(strFont);
	m_wndTip.ShowWindow(SW_HIDE);
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::Initialize
//
// DESCRIPTION:	Initials combo box
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::Initialize()
{
	// Yep tip window is created here
	m_wndTip.Create(this);

	// Set default font name
	CString strDefault = "";
	
	CFontObj* pFontObj;
	CString strKey,strComp;
	EnumerateFonts();

	POSITION pos = m_mapFonts.GetStartPosition();
	
	while (pos)
	{
		m_mapFonts.GetNextAssoc(pos,strKey,pFontObj);

		int nMax = GetCount();
		BOOL bInsert = FALSE;
		for (int nIdx=0;nIdx < nMax;nIdx++)
		{			
			GetLBText(nIdx,strComp);
			
			if (strComp.Collate(strKey) == 1)
			{
				bInsert = TRUE;
				InsertString(nIdx,strKey);
				break;
			}
		}		

		if (!bInsert)
			AddString(strKey);
	}

	// We set the timer because its the only way we know when a selection
	// has changed - use for tip window
	SetTimer(1, 500, NULL);
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::AddFont
//
// DESCRIPTION:	Adds a font to the internal array
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::AddFont(CString strName, DWORD dwFlags)
{
	CFontObj* pFontObj;	

	// Check fonts not aleady in the array
	if (!m_mapFonts.Lookup(strName,pFontObj))
		m_mapFonts.SetAt(strName,new CFontObj(dwFlags));
}

////////////////////////////////////////////////////////////////////////////////
//
// FUNCTION:	CFontCombo::OnTimer
//
// DESCRIPTION:	Positions tip window against selected font
//
// INPUTS:		
//
// RETURNS:     
//
// NOTES:       
//
// MODIFICATIONS:
//
// Name			Date      Version	Comments
// N T ALMOND   25/09/98  1.0		Origin
//
////////////////////////////////////////////////////////////////////////////////
void CFontCombo::OnTimer(UINT nIDEvent) 
{
	
	// Is combo open
	if (GetDroppedState( ))
	{
		int nSel = GetCurSel();
		
		// Selected
		if (nSel != -1)
		{
			CString str;
			GetLBText(nSel,str);
			CRect rc;
			GetDroppedControlRect(rc);

			int nHeight = GetItemHeight(0) * ((nSel - GetTopIndex()) + 1);
			
			CPoint pt(rc.right + 5,rc.top + nHeight);

			// Show tip in correct position
			m_wndTip.ShowTips(pt,str);
		}
	}
	
	
	CComboBox::OnTimer(nIDEvent);
}

BOOL CALLBACK AFX_EXPORT CFontCombo::EnumFamScreenCallBackEx(ENUMLOGFONTEX* pelf, 
	NEWTEXTMETRICEX* /*lpntm*/, int FontType, LPVOID pThis)

{
	// don't put in non-printer raster fonts
	if (FontType & RASTER_FONTTYPE)
		return 1;
	
	DWORD dwData;
	
	dwData = (FontType & TRUETYPE_FONTTYPE) ? TRUETYPE_FONT : 0;
	((CFontCombo*)pThis)->AddFont(pelf->elfLogFont.lfFaceName, dwData);
	
	return 1; // Call me back
}

BOOL CALLBACK AFX_EXPORT CFontCombo::EnumFamPrinterCallBackEx(ENUMLOGFONTEX* pelf, 
	NEWTEXTMETRICEX* /* lpntm */, int FontType, LPVOID pThis)
{
	
	if (!(FontType & DEVICE_FONTTYPE))
		return 1;

	if ((FontType & TRUETYPE_FONTTYPE))
		return 1;

	DWORD dwData = PRINTER_FONT;
	
	((CFontCombo*)pThis)->AddFont(pelf->elfLogFont.lfFaceName, dwData);
	
	return 1; // Call me back
}